package com.smart.redis.string;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.smart.redis.client.RedisClient;

import redis.clients.jedis.Jedis;

/**
 * 
 * redis 中string的数据结构模型是
 * map<k,String> 
 * 
* @ClassName: Redis2String 
* @Description: TODO redis string字符串类型数据操作 
* @Company:e-smart.top
* @author Thinkpad 
* @version 1.0 2018年8月28日 下午5:35:01
 */
public class Redis2String {

	/**
	 * 
	*
	* @Title: append 
	* @Description: TODO 把value追加到key对应的值尾部，并返回值的长度
	* @param @param key 键
	* @param @param value 要追加的字符串
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long append(String key,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long append = jedis.append(key, value);
			return append;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECR 操作。
	* 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
	* 本操作的值限制在 64 位(bit)有符号数字表示之内。
	*
	* @Title: decr 
	* @Description: TODO 对key存储的字符串数字进行减一操作 
	* @param @param key
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long decr(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long decr = jedis.decr(key);
			return decr;
		} catch (Exception e) {
			// TODO: decr 
			System.err.println("decr : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECRBY 操作。
	* 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
	* 本操作的值限制在 64 位(bit)有符号数字表示之内。
	* 
	* @Title: decrby 
	* @Description: TODO 将 key 所储存的值减去一定量值  
	* @param @param key 键
	* @param @param integer 减量
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long decrby(String key,long integer){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long decrBy = jedis.decrBy(key, integer);
			return decrBy;
		} catch (Exception e) {
			// TODO: decrBy 
			System.err.println("decrBy : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在那么返回null。
	* 假如 key 储存的值不是字符串类型，返回一个错误，因为 GET 只能用于处理字符串值。
	* 
	* @Title: get 
	* @Description: TODO 获取key对应的字符串值 
	* @param @param key
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String get(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String get = jedis.get(key);
			return get;
		} catch (Exception e) {
			// TODO: get 
			System.err.println("get : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 对值字符串的截取从start开始，end结束。
	* 负数偏移量表示从字符串最后开始计数， -1 表示最后一个字符， -2 表示倒数第二个，以此类推。
	* getrange 通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。
	* 
	* @Title: getrange 
	* @Description: TODO 取出key对应的从start到end之间的字符串 
	* @param @param key 键
	* @param @param start 开始索引 从0开始，如果是负数是按照字符串倒着开始计数
	* @param @param end 结束索引
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String getRange(String key,long start,long end){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String getrange = jedis.getrange(key, start, end);
			return getrange;
		} catch (Exception e) {
			// TODO: getrange 
			System.err.println("getrange : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: getSet 
	* @Description: TODO 给key的值设定新值，并返回旧值 
	* @param @param key
	* @param @param newValue
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String getSet(String key,String newValue){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			String oldValue = jedis.getSet(key, newValue);
			return oldValue;
		} catch (Exception e) {
			// TODO: getSet 
			System.err.println("getSet : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作。
	* 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
	* 
	* @Title: incr 
	* @Description: TODO 将 key 中储存的数字值增一
	* @param @param key
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long incr(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long incr = jedis.incr(key);
			return incr;
		} catch (Exception e) {
			// TODO: incr 
			System.err.println("incr : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCRBY 命令。
	* 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
	*
	* @Title: incrBy 
	* @Description: TODO 将 key 所储存的值加上增量 integer 。 
	* @param @param key 键
	* @param @param integer 增量
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long incrBy(String key,long integer){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Long incrBy = jedis.incrBy(key, integer);
			return incrBy;
		} catch (Exception e) {
			// TODO: incrBy 
			System.err.println("incrBy : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 不存在，那么 INCRBYFLOAT 会先将 key 的值设为 0 ，再执行加法操作。
	* 如果命令执行成功，那么 key 的值会被更新为（执行加法之后的）新值，并且新值会以字符串的形式返回给调用者。
	* 
	* @Title: incrByFloat 
	* @Description: TODO 为 key 中所储存的值加上浮点数增量 value 
	* @param @param key
	* @param @param value 增量
	* @param @return    设定文件 
	* @return Double    返回类型 
	* @throws
	 */
	public static Double incrByFloat(String key,double value){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			Double incrByFloat = jedis.incrByFloat(key, value);
			return incrByFloat;
		} catch (Exception e) {
			// TODO: incrByFloat 
			System.err.println("incrByFloat : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果给定的 key 里面，有某个 key 不存在，那么这个 key 返回特殊值 nil 。因此，该命令永不失败。
	* 
	* @Title: mget 
	* @Description: TODO 获取给key或者key集合所对应的值或值的集合
	* @param @param keys 键（集合）
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String> mget(String... keys){
		Jedis jedis = RedisClient.getJedis();
		try {
			
			List<String> mget = jedis.mget(keys);
			return mget;
		} catch (Exception e) {
			// TODO: mget 
			System.err.println("mget : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果某个给定 key 已经存在，那么 MSET 会用新值覆盖原来的旧值，
	* 如果这不是你所希望的效果，请考虑使用 MSETNX 命令：它只会在所有给定 key 都不存在的情况下进行设置操作。
	* MSET 是一个原子性(atomic)操作，所有给定 key 都会在同一时间内被设置，某些给定 key 被更新而另一些给定 key 没有改变的情况，不可能发生。
	* 
	* @Title: mset 
	* @Description: TODO  批量设置key-value（此操作可添加可更新-覆盖旧值）
	* @param @param map 键值对集合
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static Boolean mset(Map<String,String> map){
		Jedis jedis = RedisClient.getJedis();
		try {
			int index = 0;
			String[] keysvalues= new String[map.size()*2];
			for (Map.Entry<String,String> entry : map.entrySet()) { 
				keysvalues[index++]=entry.getKey();
				keysvalues[index++]=entry.getValue();
				}
			String mset = jedis.mset(keysvalues);
			System.out.println("mset : "+mset);
			//mset操作不可能失败，所以一定会返回OK
			return true;
		} catch (Exception e) {
			// TODO: mset 
			System.err.println("mset : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 即使只有一个给定 key 已存在， MSETNX 也会拒绝执行所有给定 key 的设置操作。
	* MSETNX 是原子性的，因此它可以用作设置多个不同 key 表示不同字段(field)的唯一性逻辑对象(unique logic object)，所有字段要么全被设置，要么全不被设置。
	* 要么都失败，要么都成功！
	* @Title: msetnx 
	* @Description: TODO 批量添加key-value（仅当所有给定 key 都不存在）
	* @param @param map
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean msetnx(Map<String,String> map){
		Jedis jedis = RedisClient.getJedis();
		try {
			int index = 0;
			String[] keysvalues= new String[map.size()*2];
			for (Map.Entry<String,String> entry : map.entrySet()) { 
				keysvalues[index++]=entry.getKey();
				keysvalues[index++]=entry.getValue();
				}
			Long msetnx = jedis.msetnx(keysvalues);
			
			return msetnx==1l||msetnx==1;
		} catch (Exception e) {
			// TODO: msetnx 
			System.err.println("msetnx : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: psetex 
	* @Description: TODO 以毫秒为单位设置 key-value 的生存时间 
	* @param @param key 键
	* @param @param value 值
	* @param @param milliseconds 毫秒ms
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static Boolean psetex(String key,String value,long milliseconds){
		Jedis jedis = RedisClient.getJedis();
		try {
			String psetex = jedis.psetex(key, milliseconds, value);
			System.out.println("psetex: "+psetex);
			return true;
		} catch (Exception e) {
			// TODO: psetex 
			System.err.println("psetex : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果key已经存在，直接覆盖旧值，无视类型
	* 如果原来的key有生命周期，被set后直接永久有效，会清除原有的生命周期
	*
	* @Title: set 
	* @Description: TODO 设置key-value （永久有效） 
	* @param @param key
	* @param @param value
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean set(String key,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			String set = jedis.set(key, value);
			System.out.println("set: "+set);
			return true;
		} catch (Exception e) {
			// TODO: set 
			System.err.println("set : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 如果 key 已经存在， SETEX 命令将覆写旧值。
	*
	* @Title: setex 
	* @Description: TODO 设置key-value 及其生命周期（TTL秒/s）
	* @param @param key
	* @param @param value
	* @param @param seconds
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean setex(String key,String value,int seconds){
		Jedis jedis = RedisClient.getJedis();
		try {
			String setex = jedis.setex(key, seconds, value);
			System.out.println("setex: "+setex);
			return true;
		} catch (Exception e) {
			// TODO: setex 
			System.err.println("setex : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* SET if Not eXists
	*
	* @Title: setnx 
	* @Description: TODO 添加key-value （key不存在时） 
	* @param @param key
	* @param @param value
	* @param @return    设定文件 
	* @return Boolean    返回类型 
	* @throws
	 */
	public static Boolean setnx(String key,String value){
		Jedis jedis = RedisClient.getJedis();
		try {
			Long setnx = jedis.setnx(key, value);
			return setnx==1l||setnx==1;
		} catch (Exception e) {
			// TODO: setnx 
			System.err.println("setnx : "+e.getMessage());
			return false;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	*
	* @Title: setRange 
	* @Description: TODO  从某个位置开始，复写key对应的值
	* @param @param key
	* @param @param value
	* @param @param offset
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long setRange(String key,String value,int offset){
		Jedis jedis = RedisClient.getJedis();
		try {
			Long setrange = jedis.setrange(key, offset, value);
			return setrange;
		} catch (Exception e) {
			// TODO: setrange 
			System.err.println("setrange : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	/**
	 * 
	* 当 key 储存的不是字符串值时，返回一个错误。
	* 当 key 不存在时，返回 0 
	* @Title: strlen 
	* @Description: TODO 获取key关联的字符串值的长度 
	* @param @param key
	* @param @return    设定文件 
	* @return Long    返回类型 
	* @throws
	 */
	public static Long strlen(String key){
		Jedis jedis = RedisClient.getJedis();
		try {
			Long setrange = jedis.strlen(key);
			return setrange;
		} catch (Exception e) {
			// TODO: strlen 
			System.err.println("strlen : "+e.getMessage());
			return null;
		} finally {
			RedisClient.returnToPool(jedis);
		}
	}
	
	public static void main(String[] args) {
		Map<String ,String> map =new HashMap<>();
		map.put("wowo", "1111111111");
		map.put("youwo", "22222");
		map.put("youw1", "22222");
		map.put("youw2", "22222");
		map.put("youw3", "22222");
		map.put("youw4", "22222");
		map.put("youw5", "22222");
		map.put("youw6", "22222");
		map.put("youw7", "22222");
		map.put("youw8", "22222");
		map.put("youw9", "22222");
		map.put("youw0", "22222");
		map.put("shewo", "333333");
		Redis2String.msetnx(map);
//		psetex("ssss", "wow", 60000);
	}
}
